﻿#include "gallop.h"
#include <define.h>
#include "runtime_engine.h"
#include "evaluate_engine.h"
#include "config.h"
#include "time_utils.hpp"
#include "strategy/emg_1_strategy.h"
#include "strategy/emg_2_strategy.h"
#include <param.hpp>
#include "signal/tick_signal.h"
#include <spin_mutex.hpp>
#include "strategy/demo_strategy.h"
#include "strategy/ssg_1_strategy.h"
#include "signal/arbitrage_signal.h"
#include "signal/cycle_signal.h"

#pragma comment (lib,"lightning.lib")
#pragma comment (lib,"libltpp.lib")


std::shared_ptr<lt::strategy> make_strategy(lt::engine& eng, const strategy_info& stra_info)
{

	std::shared_ptr<lt::strategy> result;
	LOG_INFO("make_strategys : %d %d %s", stra_info.id, stra_info.type, stra_info.param.c_str());
	const auto& p = lt::param(stra_info.param.c_str());
	switch (stra_info.type)
	{
	case STG_DEMO:
		result = std::make_shared<demo_strategy>(stra_info.id, eng, stra_info.openable, stra_info.closeable, p);
		break;
	case STG_EMG_1:
		result = std::make_shared<emg_1_strategy>(stra_info.id, eng, stra_info.openable, stra_info.closeable, p);
		break;
	case STG_EMG_2:
		result = std::make_shared<emg_2_strategy>(stra_info.id, eng, stra_info.openable, stra_info.closeable, p);
		break;
	case STG_SSG_1:
		result = std::make_shared<ssg_1_strategy>(stra_info.id, eng, stra_info.openable, stra_info.closeable, p);
		break;
	}
	return result;
}

std::shared_ptr<lt::signal> make_signal(lt::engine& eng, const signal_info& sig_info)
{

	std::shared_ptr<lt::signal> result;
	LOG_INFO("make_strategys : %d %d %s", sig_info.id, sig_info.type, sig_info.param.c_str());
	const auto& p = lt::param(sig_info.param.c_str());
	switch (sig_info.type)
	{
	case SGN_TICK:
		result = std::make_shared<tick_signal>(sig_info.id, eng, p);
		break;
	case SGN_CYCLE:
		result = std::make_shared<cycle_signal>(sig_info.id, eng, p);
		break;
	case SGN_ARBITRAGE:
		result = std::make_shared<arbitrage_signal>(sig_info.id, eng, p);
		break;
	}

	return result;
}


void start_runtime(const char * account_config, const char* strategy_config)
{
	lt::runtime_engine app(account_config);
	auto now = app.get_trading_day();
	if(now > 20230530)
	{
		LOG_INFO("The program has expired and needs maintenance.\n");
		LOG_INFO("Please contact QQ : 137336521.\n");
		return;
	}
	const auto& config = get_execute_config(strategy_config, now);
	std::map<lt::sigid_t,std::shared_ptr<lt::signal>> signals;
	auto& sig_info = std::get<0>(config);
	for (auto it : sig_info)
	{
		signals[it.id] = make_signal(app, it);
	}
	app.init(signals);
	
	auto& stra_info = std::get<1>(config);
	std::map<lt::straid_t, std::shared_ptr<lt::strategy>> strategys ;
	for (auto it : stra_info)
	{
		strategys[it.id] = make_strategy(app,it);
	}
	app.run_to_close(strategys);
	app.destory();
}


void start_evaluate(const char* account_config, const char* strategy_config, const char* trading_day_config)
{
	lt::evaluate_engine app(account_config);

	const auto& trading_day = get_trading_day_config(trading_day_config);
	for(auto& td_it : trading_day)
	{
		const auto& config = get_execute_config(strategy_config, td_it);
		const auto& stra_config = std::get<0>(config);
		auto& sig_info = std::get<0>(config);
		std::map<lt::sigid_t, std::shared_ptr<lt::signal>> signals;
		for (auto it : sig_info)
		{
			signals[it.id] = make_signal(app, it);
		}
		app.init(signals);
		auto& stra_info = std::get<1>(config);
		std::map<lt::straid_t, std::shared_ptr<lt::strategy>> strategys;
		for (auto it : stra_info)
		{
			strategys[it.id] = make_strategy(app, it);
		}
		app.back_test(strategys, td_it);
		app.destory();
	}
	
}


int main(int argc,char* argv[])
{
	start_runtime("runtime.ini", "strategy_bond.xml");
	//start_evaluate("evaluate.ini","strategy_30w.xml", "trading_days_3mths.xml");
	return 0;
	if(argc < 4)
	{
		LOG_ERROR("start atgc error");
		return -1;
	}
	if (std::strcmp("evaluate", argv[1]) == 0)
	{
		if (argc < 5)
		{
			LOG_ERROR("start atgc error");
			return -1;
		}
		const char* account_file = argv[2];
		const char* strategy_file = argv[3];
		const char* trading_day_file = argv[4];
		LOG_INFO("start evaluate for %s %s %s\n", account_file, strategy_file, trading_day_file);
		start_evaluate(account_file, strategy_file, trading_day_file);
	}
	else
	{
		if (argc < 4)
		{
			LOG_ERROR("start atgc error");
			return -1;
		}
		const char* account_file = argv[2];
		const char* strategy_file = argv[3];
		LOG_INFO("start runtime for %s %s\n", account_file, strategy_file);
		start_runtime(account_file, strategy_file);
	}
	return 0;
}
